home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / util4 / noiz.lha / noiz.c < prev    next >
C/C++ Source or Header  |  1996-01-16  |  11KB  |  384 lines

  1.  
  2.  
  3. /* noiz.c
  4.  *
  5.  *  Adapted for Amiga computers by C.R. 'Magius' Hahn from noiz-0.5 by
  6.  *  Henry Strickland <strick@yak.net>.  MD5 implementation by Colin Plumb
  7.  *
  8.  *  This is essentially an integrated form of noiz-0.5 for Amiga personal
  9.  *  computers running OS 2.0 or greater
  10.  *
  11.  */
  12.  
  13. /*  Usage: NOIZ [FILE <noizfile>] [TO <file>] [STIR] [ASCII] [INIT]
  14.  *  If 'TO' keyword is not given, standard output is used, and output
  15.  *  is ASCII, regardless of the absence of the 'ASCII' switch
  16.  *
  17.  *  FILE keyword specifies noiz state file to use.  If not given,
  18.  *      default is "s:noiz".  If the file does not exist, it is
  19.  *      created and initialized as per INIT switch described below.
  20.  *      The environment variable, NOIZFILE, is also recognized, and
  21.  *      overrides the default, but is overridden by the FILE keyword.
  22.  *  TO keyword specifies output file
  23.  *  STIR invokes the noizstir function
  24.  *  ASCII switch causes output to be produced in human-readable form.
  25.  *  INIT switch causes noise state file to be created and initialized
  26.  *      before any other action is performed.  If the state file already
  27.  *      exists, a warning is printed, and the file is left unchanged.
  28.  *      NOTE: As the state file will be automatically created if it does
  29.  *      not exist, this switch is not really necessary.
  30.  *
  31.  *  Examples:
  32.  *  NOIZ
  33.  *      prints 16 bytes of noise, in ASCII.
  34.  *      equivalent to: noizspin | noizout | od
  35.  *  NOIZ STIR
  36.  *      'stirs' the noise state file.
  37.  *      equivalent to: noizspin | noizstir
  38.  *  NOIZ TO outfile STIR
  39.  *      'stirs' the noise state file and writes 16 bytes of noise to
  40.  *      outfile.
  41.  *      equivalent to: noizspin | noizstir
  42.  *                     noizspin | noizout >outfile
  43.  *  NOIZ TO outfile ASCII
  44.  *      prints 16 bytes of noise, in ASCII, to outfile.
  45.  *      equivalent to: noizspin | noizout | od >outfile
  46.  *  NOIZ FILE=sys:t/noizyfile INIT
  47.  *      Creates and initializes sys:t/noizyfile, provided it is not
  48.  *      already present.
  49.  *      equivalent to: noizinit
  50.  *          (but acts on sys:t/noizyfile instead of /etc/noiz)
  51.  *
  52.  */
  53.  
  54. #include <exec/types.h>
  55. #include <exec/alerts.h>
  56. #include <dos/dos.h>
  57.  
  58. #include <clib/exec_protos.h>
  59. #include <clib/dos_protos.h>
  60.  
  61. #include <time.h>
  62. #include "md5.h"
  63.  
  64. /* ARG numbers - we use these to index into Args[] (see below) */
  65. #define ARG_FILE    0
  66. #define ARG_TO      1
  67. #define ARG_STIR    2
  68. #define ARG_ASCII   3
  69. #define ARG_INIT    4
  70.  
  71. /* standard AmigaDOS version string */
  72. /* Note that the correct form for the date is (dd.mm.yy) */
  73. UBYTE *VerS = "$VER: NOIZ 0.5 (11.01.96) by Henry Strickland <strick@yak.net>  Amiga version by C.R. 'Magius' Hahn";
  74.  
  75. /* Command-line template, used by ReadArgs system call */
  76. UBYTE *Template = "FILE/K,TO/K,STIR/S,ASCII/S,INIT/S";
  77.  
  78. struct RDargs *rda=NULL;    /* 'placeholder' used by ReadArgs */
  79. UBYTE *Args[5] = {          /* ReadArgs fills this in for us */
  80.     NULL,   /* FILE/K keyword arg */
  81.     NULL,   /* TO/K keywork arg */
  82.     NULL,   /* STIR/S switch arg */
  83.     NULL,   /* ASCII/S switch arg */
  84.     NULL    /* INIT/S switch arg */
  85. };
  86.  
  87. /* The following two BOOL's are used instead of their */
  88. /* equivalents in Args[] to implement some rather */
  89. /* obscure behavior (see docs) */
  90. BOOL Produce_Output = FALSE;
  91. BOOL ASCII_Output = FALSE;
  92.  
  93. /* What's the name of the noise state file? */
  94. UBYTE *StateFile = "S:noiz";
  95. UBYTE sfBuf[80];
  96.  
  97. /* Exec Library base pointer - this is set up by the starup code, */
  98. /* but we need to be able to examine it to determine what version */
  99. /* of the OS we are running under */
  100. extern struct Library *SysBase;
  101.  
  102.  
  103. void safecleanup(void);
  104. BOOL statefile_exists(void);
  105. BOOL init_statefile(void);
  106.  
  107. int main(void)
  108. {
  109.  
  110.     /* First, make sure we are running under release 2.0 (v36) or */
  111.     /* better, because ReadArgs is not present on earlier systems */
  112.     /* (also, we want to use buffered IO FGets, FPutc, and so on */
  113.     /* which are not present pre-v36 */
  114.     if(SysBase->lib_Version < 36)
  115.     {
  116.         /* OS is too primitive for us, tell user to get a life. */
  117.         /* Write is used here to avoid having to bring in */
  118.         /* stdio from c.lib - makes the prog smaller */
  119.         Write(Output(),"AmigaOS release 2.0 or higher required.\n",40);
  120.         return(RETURN_FAIL);
  121.     }
  122.  
  123.  
  124.     /* great, now we register our 'cleanup' function with atexit, so */
  125.     /* we don't have to worry about freeing resources if we have to */
  126.     /* bail out later */
  127.     if(atexit(safecleanup))
  128.     {
  129.         /* oh-oh, this should never happen - if it does, the */
  130.         /* machine is probably so screwed up it'll never be */
  131.         /* able to execute any code we might put here.. */
  132.         /* The system call, Alert(), probably has the best */
  133.         /* shot here, so we'll try that..  Since we don't */
  134.         /* know what actually caused us to get screwed up */
  135.         /* we'll pass AN_Unknown as an alert code */
  136.         Alert(AN_Unknown);
  137.         return(RETURN_FAIL);
  138.     }
  139.  
  140.     rda = ReadArgs(Template, Args, NULL);
  141.     if(!rda)
  142.     {
  143.         /* Again, this should not happen, */
  144.         Alert(AN_Unknown);
  145.         return(RETURN_FAIL);
  146.     }
  147.  
  148.     /* Now, set up our additional globals */
  149.     /* produce output only if neither of INIT or STIR are given, OR */
  150.     /* if output is implicitly enabled via TO or ASCII */
  151.     Produce_Output = (!(Args[ARG_STIR] || Args[ARG_INIT])) || (Args[ARG_TO] || Args[ARG_ASCII]);
  152.     ASCII_Output = Args[ARG_ASCII] || (!Args[ARG_TO]);
  153.  
  154.     /* Now decide where the noise state file can be found.  This */
  155.     /* would be /etc/noiz under UNIX, but we default to S:noiz */
  156.     /* We also allow the user to specify a different file via the */
  157.     /* command line, or an environment variable */
  158.     if(Args[ARG_FILE]) StateFile = Args[ARG_FILE];
  159.     else
  160.     {
  161.         BPTR sfile;
  162.  
  163.         sfile = Open("ENV:NOIZFILE",MODE_OLDFILE);
  164.         if(sfile)
  165.         {
  166.             FGets(sfile,sfBuf,80);
  167.             StateFile = sfBuf;
  168.             Close(sfile);
  169.         }
  170.     }
  171.  
  172.  
  173.     if(statefile_exists())
  174.     {
  175.         if(Args[ARG_INIT])
  176.         {
  177.             /* Rather that print our own error message here, I */
  178.             /* have DOS perform the task, since DOS (2.1 or better) */
  179.             /* knows how to print an error message in the user's */
  180.             /* preferred language.   *Objekt existiert bereits* */
  181.             PrintFault(ERROR_OBJECT_EXISTS,StateFile);
  182.         }
  183.     }
  184.     else
  185.     {
  186.         /* If the statefile doesn't exist, create and initialize it. */
  187.         if(!init_statefile())
  188.         {
  189.             /* DAMN.. can't create statefile - maybe the user */
  190.             /* gave a faulty filename.  Let DOS handle this */
  191.             PrintFault(IoErr(),StateFile);
  192.             return(RETURN_FAIL);
  193.         }
  194.     }
  195.  
  196.     if(Args[ARG_STIR])
  197.     {
  198.         BYTE noiz[256];
  199.         BYTE pad[256];
  200.         UBYTE in_hash[16];
  201.         UBYTE out_hash[16];
  202.  
  203.         struct MD5Context context;
  204.         int e,i,seconds,row;
  205.         long pid;
  206.         long ppid;
  207.         BPTR fh;
  208.  
  209.  
  210.         /* Seed the c.lib's pseudorandom number generator */
  211.         /* which we use because we don't really have */
  212.         /* anything better (this replaces noizspin) */
  213.         srand(time(NULL)^(ULONG)FindTask(NULL));
  214.  
  215.         /* This stuff is basically the same as the original noizstir */
  216.         /* code except that we use AmigaDOS calls instead of stdio */
  217.         fh = Open(StateFile,MODE_OLDFILE);
  218.         if(!fh)
  219.         {
  220.             PrintFault(IoErr(),StateFile);
  221.             return(RETURN_FAIL);
  222.         }
  223.  
  224.         Read(fh,noiz,256);
  225.  
  226.         MD5Init( &context );
  227.         MD5Update(&context, noiz, 256);
  228.         sprintf(pad,"%d",rand());
  229.         MD5Update(&context, pad, 256);
  230.         time( &seconds );
  231.         pid= rand();
  232.         ppid= FindTask(NULL);
  233.         MD5Update( &context, (UBYTE *) &seconds, sizeof seconds );
  234.         MD5Update( &context, (UBYTE *) &pid, sizeof pid );
  235.         MD5Update( &context, (UBYTE *) &ppid, sizeof ppid );
  236.         MD5Final( in_hash, &context );
  237.  
  238.         for (row=0; row<16; row++ ) {
  239.                 MD5Init( &context );
  240.                 MD5Update( &context, noiz+16*row, 16 );
  241.                 MD5Update( &context, in_hash, 16 );
  242.                 MD5Update( &context, in_hash, row+1 );
  243.                 MD5Final( out_hash, &context );
  244.                 for ( i=0; i<16; i++ ) {
  245.                         noiz[16*row+i] ^= out_hash[i];
  246.                 }
  247.         }
  248.  
  249.         Seek(fh,0,OFFSET_BEGINNING);
  250.         e = Write(fh, noiz, 256);
  251.         if(e == -1)
  252.         {
  253.             PrintFault(IoErr(),StateFile);
  254.         }
  255.         Close(fh);
  256.     }
  257.     if(Produce_Output)
  258.     {
  259.         BYTE noiz[256];
  260.         BYTE pad[256];
  261.         UBYTE out_hash[16];
  262.         struct MD5Context context;
  263.         int seconds, pid, ppid;
  264.         BPTR fh;
  265.  
  266.         /* Seed the c.lib's pseudorandom number generator */
  267.         /* which we use because we don't really have */
  268.         /* anything better */
  269.         srand(time(NULL)^(LONG)FindTask(NULL));
  270.  
  271.         /* This stuff is basically the same as the original noizout */
  272.         /* code except that we use AmigaDOS calls instead of stdio */
  273.         fh = Open(StateFile,MODE_OLDFILE);
  274.         if(!fh)
  275.         {
  276.             PrintFault(IoErr(),StateFile);
  277.             return(RETURN_FAIL);
  278.         }
  279.  
  280.         Read(fh, noiz, 256);
  281.         Close(fh);
  282.         sprintf(pad,"%d\n",rand());
  283.  
  284.         MD5Init( &context );
  285.         MD5Update(&context, noiz, 256);
  286.         MD5Update(&context, pad, 256);
  287.         time( &seconds );
  288.         pid= rand();
  289.         ppid= FindTask(NULL);
  290.         MD5Update( &context, (UBYTE *) &seconds, sizeof seconds );
  291.         MD5Update( &context, (UBYTE *) &pid, sizeof pid );
  292.         MD5Update( &context, (UBYTE *) &ppid, sizeof ppid );
  293.         MD5Final( out_hash, &context );
  294.  
  295.         if(Args[ARG_TO])
  296.         {
  297.             fh = Open(Args[ARG_TO],MODE_NEWFILE);
  298.             if(!fh)
  299.             {
  300.                 PrintFault(IoErr(),Args[ARG_TO]);
  301.                 return(RETURN_FAIL);
  302.             }
  303.             if(Args[ARG_ASCII])
  304.             {
  305.                 char out[20];
  306.                 int j;
  307.  
  308.                 FPuts(fh,"0x");
  309.                 for(j=0;j<16;j++)
  310.                 {
  311.                     sprintf(out,"%02X",out_hash[j]);
  312.                     FPuts(fh,out);
  313.                 }
  314.                 FPuts(fh,"\n");
  315.             }
  316.             else
  317.             {
  318.                 Write(fh,out_hash,16);
  319.             }
  320.             Close(fh);
  321.         }
  322.         else
  323.         {
  324.             char out[20];
  325.             int j;
  326.  
  327.             PutStr("0x");
  328.             for(j=0;j<16;j++)
  329.             {
  330.                 sprintf(out,"%02X",out_hash[j]);
  331.                 PutStr(out);
  332.             }
  333.             PutStr("\n");
  334.         }
  335.     }
  336.     return(RETURN_OK);
  337. }
  338.  
  339.  
  340. BOOL statefile_exists(void)
  341. {
  342.     BPTR lock;
  343.     BOOL rv;
  344.  
  345.     lock = Lock(StateFile,SHARED_LOCK);
  346.     if(lock)
  347.     {
  348.         rv = TRUE;
  349.         UnLock(lock);
  350.     }
  351.     else rv = FALSE;
  352.     return(rv);
  353. }
  354.  
  355.  
  356. BOOL init_statefile(void)
  357. {
  358.     BPTR file;
  359.     int i, e;
  360.  
  361.     file = Open(StateFile,MODE_NEWFILE);
  362.     if(!file)
  363.     {
  364.         return(FALSE);
  365.     }
  366.     for(i=0; i<256; i++)
  367.     {
  368.         e = FPutC(file,i);
  369.         if(e < 0)
  370.         {
  371.             Close(file);
  372.             return(FALSE);
  373.         }
  374.     }
  375.     Close(file);
  376.     return(TRUE);
  377. }
  378.  
  379.  
  380. void safecleanup(void)
  381. {
  382.     if(rda) FreeArgs(rda);
  383. }
  384.